package com.info.zhiduoduo.admin.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.CellData;
import com.baomidou.mybatisplus.mapper.Condition;
import com.info.zhiduoduo.admin.model.formbean.crowdsource.ImportCrowdsourceProjectFormBean;
import com.info.zhiduoduo.admin.model.vo.crowdsource.ImportCrowdsourceProjectVO;
import com.info.zhiduoduo.common.constants.Constants;
import com.info.zhiduoduo.common.constants.SmartResult;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceUserType;
import com.info.zhiduoduo.common.constants.maker.StudioState;
import com.info.zhiduoduo.common.constants.pay.PayTypeSn;
import com.info.zhiduoduo.common.constants.project.CalcAmountType;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.common.utils.StringUtil;
import com.info.zhiduoduo.core.listener.BaseAnalysisEventListener;
import com.info.zhiduoduo.core.service.CoreSensitiveService;
import com.info.zhiduoduo.core.service.CrowdsourceProjectService;
import com.info.zhiduoduo.repository.dto.crowdsource.CalcCrowdsourceItemAmountModel;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceItemAmountCalcResult;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceProjectDetailDto;
import com.info.zhiduoduo.repository.dto.maker.MakerDetailDto;
import com.info.zhiduoduo.repository.entity.company.Company;
import com.info.zhiduoduo.repository.entity.company.CompanyParty;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceAccount;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceProject;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceProjectItem;
import com.info.zhiduoduo.repository.entity.quota.CrowdsourceCityQuota;
import com.info.zhiduoduo.repository.mapper.maker.MakerMapper;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tianyonghong
 * @create 2022/7/21
 */
@Getter
@Slf4j
@Transactional
public class CrowdsourceProjectUploadListener extends BaseAnalysisEventListener<ImportCrowdsourceProjectFormBean> {
    private static final int BATCH_COUNT = 500;
    //解析后的数据集合s
    List<ImportCrowdsourceProjectFormBean> list = new ArrayList<>();

    //解析后的数据集合
    List<CrowdsourceItemAmountCalcResult> itemAmountCalcList = new ArrayList<>();

    //计算项目金额/税费返回数据集合
    Map<Integer,BigDecimal> calcTaxFeeMap = new HashMap<>();
    Map<Integer,BigDecimal> calcProjectAmountMap = new HashMap<>();

    Integer fileRecordId;
    Integer projectType;
    Double partnerBrokerageRate;
    Company company;
    CompanyParty companyParty;
    CrowdsourceCityQuota personalQuota;
    MakerMapper makerMapper;
    CrowdsourceProjectService crowdsourceProjectService;
    CoreSensitiveService coreSensitiveService;
    //智零工项目类型: 1:智众包(默认)，2:智零工")
    Integer workType;
    Integer createBy;
    //税源地税率
    BigDecimal taxSourceCostRate;

    public CrowdsourceProjectUploadListener(Company company, CompanyParty companyParty, CrowdsourceCityQuota personalQuota,
                                            Integer projectType, Integer fileRecordId, Integer workType,Integer createBy,
                                            BigDecimal taxSourceCostRate, Double partnerBrokerageRate, CrowdsourceProjectService crowdsourceProjectService,
                                            CoreSensitiveService coreSensitiveService,
                                            MakerMapper makerMapper) {
        this.company = company;
        this.companyParty = companyParty;
        this.personalQuota = personalQuota;
        this.projectType = projectType;
        this.fileRecordId = fileRecordId;
        this.workType = workType;
        this.createBy = createBy;
        this.taxSourceCostRate = taxSourceCostRate;
        this.partnerBrokerageRate = partnerBrokerageRate;
        this.crowdsourceProjectService = crowdsourceProjectService;
        this.coreSensitiveService = coreSensitiveService;
        this.makerMapper = makerMapper;
    }

    /**
     * 读取excel表头，校验表头是否正确
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
        int index = context.readRowHolder().getRowIndex() + 1;
        // 第四行企业名称校验
        if (index == 4) {
            //返回名字
            if (headMap.size() < 2 || StringUtils.isBlank(headMap.get(1).getStringValue())) {
                throw new ExcelAnalysisException(StatusMsg.StatusMsg_345.getMsg());
            }
            String compname = headMap.get(1).getStringValue();
            String n1 = compname.replaceAll("\\(|\\)|（|）", "");
            String n2 = this.company.getCompname().replaceAll("\\(|\\)|（|）", "");
            if(!StringUtils.equals(n1,n2)){
                throw new ExcelAnalysisException(StatusMsg.StatusMsg_345.getMsg());
            }
        }
    }

    /**
     * 每一条数据解析都会调用
     */
    @Override
    public void invoke(ImportCrowdsourceProjectFormBean formBean, AnalysisContext analysisContext) {
//        Integer rowNumber = analysisContext.readSheetHolder().getApproximateTotalRowNumber();
        if (index > BATCH_COUNT) {
            throw new ExcelAnalysisException("单次派发人数不能超过500人");
        }
        super.invoke(formBean, analysisContext);
        // 数据校验
        if (checkValidExcelData(formBean, index)) {
            // 创客限额校验
            if (checkMakerQuota(formBean, index)) {
                list.add(formBean);
            }
        }
    }

    /**
     * 数据有效性校验，返回" 项目"对象
     *
     * @return
     */
    private boolean checkValidExcelData(ImportCrowdsourceProjectFormBean formBean, int index) {
        //校验敏感词
        String checkName = coreSensitiveService.checkSensitiveWords(formBean.getProjectName());
        String checkDesc = coreSensitiveService.checkSensitiveWords(formBean.getProjectDesc());
        if (StringUtil.isNotEmpty(checkName) || StringUtil.isNotEmpty(checkDesc)) {
            if (StringUtil.isNotEmpty(checkName)) {
                errorPrompt.add("请检查第[" + index + "]行数据：项目名称存在敏感词：" + checkName);
            }
            if (StringUtil.isNotEmpty(checkDesc)) {
                errorPrompt.add("请检查第[" + index + "]行数据：项目描述存在敏感词：" + checkDesc);
            }
            return false;
        }

        // 智众包匹配创客，智零工匹配自然人，匹配并设置userid,name
        if (workType == Constants.WORK_TYPE_1) {
            //校验企业是否有这个开票内容，没有的话提示：发票内容不匹配，该企业可开票内容有【**********】
            if(!StringUtils.contains(company.getInvoiceScope(),formBean.getInvoiceContent().trim())){
                errorPrompt.add("请检查第[" + index + "]行数据：发票内容不匹配，贵司可开票内容有【" + company.getInvoiceScope().replace("?","，") + "】");
                return false;
            }
            boolean isMatch = matchMaker(formBean);
            if(!isMatch){
                return false;
            }
        } else {
            //校验企业是否有这个开票内容，没有的话提示：发票内容不匹配，该企业可开票内容有【**********】
            if(!StringUtils.contains(company.getInvoiceScopeOdd(),formBean.getInvoiceContent().trim())){
                errorPrompt.add("请检查第[" + index + "]行数据：发票内容不匹配，贵司可开票内容有【" + company.getInvoiceScopeOdd().replace("?","，") + "】");
                return false;
            }
            boolean isMatch = matchCrowdsource(formBean);
            if(!isMatch){
                return false;
            }
        }

        formBean.setProjectAmount(formBean.getItemAmount());
        return true;
    }

    /**
     * @return
     */
    private boolean checkMakerQuota(ImportCrowdsourceProjectFormBean formBean, int index) {
        //计算各个小项目金额
        CalcCrowdsourceItemAmountModel model = CalcCrowdsourceItemAmountModel.of(partnerBrokerageRate, company, formBean.getUserId(),
                formBean.getUserType(), formBean.getProjectAmount(), CalcAmountType.ALL, workType, companyParty.getCityId());

        CrowdsourceItemAmountCalcResult itemAmountCalc = null;

        BigDecimal lastTaxFee = BigDecimal.ZERO;
        BigDecimal lastProjectAmount = BigDecimal.ZERO;
        if (calcTaxFeeMap.get(formBean.getUserId()) != null) {
            lastTaxFee = calcTaxFeeMap.get(formBean.getUserId());
            lastProjectAmount = calcProjectAmountMap.get(formBean.getUserId());
        }
        itemAmountCalc = crowdsourceProjectService.calcItemAmountRepeat(lastProjectAmount, lastTaxFee, model);
        calcTaxFeeMap.put(formBean.getUserId(), lastTaxFee.add(itemAmountCalc.getProjectServiceCharge()));
        calcProjectAmountMap.put(formBean.getUserId(), lastProjectAmount.add(itemAmountCalc.getProjectAmount()));

        // 创客工作室限额
        CrowdsourceCityQuota studioQuota = null;
        if (itemAmountCalc.getUserType() == CrowdsourceUserType.STUDIO) {
            studioQuota = crowdsourceProjectService.findStudioCityQuota(formBean.getUserId());
        }
        // 计算各个限额
        crowdsourceProjectService.handleProjectItemCalcQuota(company, itemAmountCalc, personalQuota, studioQuota);

        // 表示众包创客限额超过了，过滤掉
        if (itemAmountCalc.getMakerExceedType() != 0 || itemAmountCalc.getMakerExceedPeriod() != 0) {
            //1：过去12个月 2：年 3：季度 4：月 5：单笔
            if (itemAmountCalc.getMakerExceedType() == 1) {
                errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超年度最高限额");
                return false;
            } else {
                if (itemAmountCalc.getMakerExceedPeriod() == 1) {
                    if(itemAmountCalc.getMakerExceedType() == 2) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超连续12个月累计交易限额");
                        return false;
                    } else if(itemAmountCalc.getMakerExceedType() == 5) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超个人连续12个月交易限额");
                        return false;
                    }
                } else if (itemAmountCalc.getMakerExceedPeriod() == 2) {
                    if (itemAmountCalc.getMakerExceedType() == 2) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超企业年度限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 3) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超年度限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 4) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超注册地年度限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 5) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超个人全年交易限额");
                        return false;
                    } else {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超年度限额");
                        return false;
                    }
                } else if (itemAmountCalc.getMakerExceedPeriod() == 3) {
                    if (itemAmountCalc.getMakerExceedType() == 2) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超企业季度限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 3) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超季度限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 4) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超注册地季度限额");
                        return false;
                    } else {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超季度限额");
                        return false;
                    }
                } else if (itemAmountCalc.getMakerExceedPeriod() == 4) {
                    if (itemAmountCalc.getMakerExceedType() == 2) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超企业月度限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 3) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超月度限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 4) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超注册地月度限额");
                        return false;
                    } else {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超月度限额");
                        return false;
                    }
                } else if (itemAmountCalc.getMakerExceedPeriod() == 5) {
                    if (itemAmountCalc.getMakerExceedType() == 2) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超单笔限额");
                        return false;
                    } else if (itemAmountCalc.getMakerExceedType() == 3) {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超单笔限额");
                        return false;
                    } else {
                        errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超单笔限额");
                        return false;
                    }
                } else {
                    errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超限额");
                    return false;
                }
            }
        }
        if (itemAmountCalc.isSingleExceed()) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超注册地单笔限额");
            return false;
        }
        if (itemAmountCalc.isMonthlyExceed()) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超注册地月度限额");
            return false;
        }
        if (itemAmountCalc.isQuarterlyExceed()) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超注册地季度限额");
            return false;
        }
        if (itemAmountCalc.isYearlyExceed()) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】已超注册地年度限额");
            return false;
        }
        // 保存计算结果的金额
        formBean.setItemAmountCalc(itemAmountCalc);
        return true;
    }

    /**
     * 所有数据解析完成了调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        ImportCrowdsourceProjectVO vo = new ImportCrowdsourceProjectVO();
        vo.setErrorPrompt(errorPrompt);

        // 有失败的数据，则返回
        if (CollectionUtils.isNotEmpty(errorPrompt)) {
            smartResult = SmartResult.fail(StatusMsg.StatusMsg_1109, vo);
            return;
        }

        List<CrowdsourceProjectDetailDto> dtos = new ArrayList<>();
        // 所有数据检测成功，新增
        // 按项目名分组
        Map<String, List<ImportCrowdsourceProjectFormBean>> map = list.stream()
                                                                      .collect(Collectors.groupingBy(ImportCrowdsourceProjectFormBean::getProjectName));

        Collection<List<ImportCrowdsourceProjectFormBean>> collection = map.values();

        for (List<ImportCrowdsourceProjectFormBean> list : collection) {
            ImportCrowdsourceProjectFormBean formBean = list.get(0);

            // 项目信息
            CrowdsourceProject project = getBaseProjectInfo();
            project.setProjectName(formBean.getProjectName())
                   .setProjectDesc(formBean.getProjectDesc())
                   .setInvoiceContent(formBean.getInvoiceContent())
                   .setSourceFileId(fileRecordId);

            // 处理项目的单条金额
            if (project.insert()) {
                // 添加各个小项目
                for (ImportCrowdsourceProjectFormBean itemFormBean : list) {
                    //新建
                    CrowdsourceProjectItem projectItem = new CrowdsourceProjectItem().setProjectid(project.getProjectid())
                                                                                     .setProjectAmount(itemFormBean.getProjectAmount())
                                                                                     .setUserid(itemFormBean.getUserId())
                                                                                     .setUserType(itemFormBean.getUserType())
                                                                                     .setRealname(itemFormBean.getRealname())
                                                                                     .setUsername(itemFormBean.getUsername());
                    projectItem.setProjectServiceCharge(itemFormBean.getItemAmountCalc().getProjectServiceCharge());
                    projectItem.setDepositRate(company.getDepositRate());
                    projectItem.setDepositAmount(itemFormBean.getItemAmountCalc().getDepositAmount());
                    projectItem.setIntegratedTaxFee(itemFormBean.getItemAmountCalc().getIntegratedTaxFee());
                    projectItem.setTaxRate(itemFormBean.getItemAmountCalc().getTaxRate());
                    projectItem.setPartnerBrokerage(itemFormBean.getItemAmountCalc().getPartnerBrokerage());
                    projectItem.insert();
                }
                //刷新智众包项目
                CrowdsourceProjectDetailDto detailDto = crowdsourceProjectService.refreshProjectDetail(project);
                dtos.add(detailDto);
            }
        }
        BigDecimal totalAmount = dtos.stream()
                                     .map(CrowdsourceProjectDetailDto::getProjectTotalAmount)
                                     .reduce(BigDecimal.ZERO, BigDecimal::add)
                                     .setScale(2, BigDecimal.ROUND_HALF_UP);
        vo.setTotalCount(dtos.size());
        vo.setTotalAmount(totalAmount);
        vo.setSuccessList(dtos);
        smartResult = SmartResult.success(vo);
    }

    /**
     * 构建项目基础信息
     *
     * @return
     */
    public CrowdsourceProject getBaseProjectInfo() {
        // 项目信息
        double baseTaxRate = workType == Constants.WORK_TYPE_1 ? company.getBaseTaxRate() : company.getBaseTaxRateOdd();
        return new CrowdsourceProject().setCompid(company.getCompid())
                                       .setCompname(company.getCompname())
                                       .setDepositRate(company.getDepositRate())
                                       .setProjectType(projectType)
                                       .setBaseTaxRate(baseTaxRate)
                                       .setLowTaxRate(company.getLowTaxRate())
                                       .setHighTaxRate(company.getHighTaxRate())
                                       .setProjectServiceRate(company.getProjectServiceRate())
                                       .setPartnerBrokerageRate(partnerBrokerageRate)
                                       .setPartyId(companyParty.getPartyId())
                                       .setPayId(companyParty.getPayId())
                                       .setCrowdsourceCity(companyParty.getCityId())
                                       .setState(Constants.CROWDSOURCE_PROJECT_CREATE)
                                       .setWorkType(workType)
                                       .setCreateBy(createBy)
                                       .setCreateType(2)
                                       .setTaxSourceId(companyParty.getTaxSourceId())
                                       .setTaxSourceCostRate(taxSourceCostRate);
    }

    //匹配创客
    public Boolean matchMaker(ImportCrowdsourceProjectFormBean formBean) {
        Integer userid = makerMapper.findValidUseridByIdno(formBean.getIdno());
        if (userid == null || userid == 0) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】身份证号不匹配");
            return false;
        }

        MakerDetailDto studio = makerMapper.getUserData(userid);
        if (studio == null) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客未找到");
            return false;
        }
        if (!StringUtils.equals(studio.getRealname(),formBean.getName())) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客姓名不匹配");
            return false;
        }
        MakerDetailDto userDetail = makerMapper.getUserState(studio.getUserid());
        // 2022.12.30 增加如果企业支付方式是支付宝 判断创客是否填写支付宝账号
        if (PayTypeSn.ZFB.equals(companyParty.getPayTypeSn())) {
            if (StringUtil.isEmpty(studio.getAlipayAccount())) {
                errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客未填写支付宝账号");
                return false;
            }
            if (!StringUtils.equals(studio.getAlipayAccount(),formBean.getAcctno())) {
                errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】收款方支付宝账号不匹配");
                return false;
            }
        } else {
            if (!StringUtils.equals(studio.getAcctno(),formBean.getAcctno())) {
                errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客收款方账户不匹配");
                return false;
            }
        }
        if (!NumberUtil.equals(studio.getStudioState(), StudioState.CONFIRMED)) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客未开户");
            return false;
        }
        // 天津/芜湖创客还未开税户的不能发单
        else if (NumberUtil.intIn(studio.getOpeningLocation(), 1, 3) && !NumberUtil.equals(studio.getTaxAcctState(), 3)) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客未开税户");
            return false;
        }
        // 创客已经注销/申请注销已受理，不能发布项目
        if (NumberUtil.equals(studio.getState(), Constants.user_state_4)) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客已注销，不能发布项目");
            return false;
        }
        if (NumberUtil.equals(userDetail.getRescissionState(), Constants.user_rescission_state_2)) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】创客申请注销已受理，不能发布项目");
            return false;
        }
        //设置数据
        formBean.setUserId(studio.getUserid());
        formBean.setUserType(CrowdsourceUserType.STUDIO);
        formBean.setUsername(studio.getUsername());
        formBean.setRealname(studio.getRealname());
        return true;
    }

    /**
     * 匹配自然人 根据身份证匹配自然人，再匹配姓名和账户
     * @param formBean
     */
    public boolean matchCrowdsource(ImportCrowdsourceProjectFormBean formBean) {
        //查询自然人
        CrowdsourceAccount account = new CrowdsourceAccount().selectOne(Condition.create()
                                                                                 .eq("idno", formBean.getIdno())
                                                                                 .last(" limit 1 ")
                                                                                 .orderDesc(Arrays.asList("createtime")));
        if (account == null) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】自然人身份证号不匹配");
            return false;
        }
        if(!account.getRealname().equals(formBean.getName())){
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】自然人姓名不匹配");
            return false;
        }
        if(!account.getAcctno().equals(formBean.getAcctno())){
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】自然人账户不匹配");
            return false;
        }
        if (account.getRealnameAuth() != Constants.crowdsource_auth_3) {
            errorPrompt.add("请检查第[" + index + "]行数据：【" + formBean.getName() + "】自然人未实名认证");
            return false;
        }

        formBean.setUserId(account.getCrowdsourceid());
        formBean.setRealname(formBean.getName());
        formBean.setUserType(CrowdsourceUserType.NATURAL_PERSON);
        return true;
    }
}
